﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Csharp.Equality {
    public struct PointStruct : IEquatable<PointStruct> {
        /*Any field that will be used for equality comparisons
         * must be immutable. This usually means that either
         * all properties on the class are read-only or the 
         * class has a unique identifier like a database key.*/
        readonly Int32 _X;
        readonly Int32 _Y;

        public PointStruct(Int32 x, Int32 y) {
            _X = x;
            _Y = y;
        }

        public Int32 X {
            get { return _X; }
        }

        public Int32 Y {
            get { return _Y; }
        }

        public bool Equals(PointStruct other) {
            /* Should base this comparison on the hash code
             * of each object. That way, if fields are added
             * or changed, you only have to update how the
             * hash code is calculated. All equality methods
             * are automatically updated. */
            return (GetHashCode() == other.GetHashCode());
        }

        // Sealed to prevent subclasses from breaking equality.
        public override bool Equals(object obj) {
            if (obj is PointStruct)
                return Equals((PointStruct)obj);
            else
                return false;
        }

        public override int GetHashCode() {
            /* The easiest way derive a hash code is to
             * simply use an exclusive or on the hash 
             * codes of all the fields used for equality.*/
            return _X.GetHashCode() ^ _Y.GetHashCode();
        }

        public static bool operator ==(PointStruct point1, PointStruct point2) {
            return point1.Equals(point2);
        }

        public static bool operator !=(PointStruct point1, PointStruct point2) {
            return !(point1 == point2);
        }
    }
}
